import uuid
from django.http import JsonResponse
from django import forms
from datetime import datetime

from BloodSpiderModel.DjangoResponseTool.response_dict import response_dict, get_first_error, get_page
from BloodSpiderAPI import models
from BloodSpiderAPI.apis.task import utils as task_utils
from django.db.models import Q


# Task表单验证
class TaskForm(forms.ModelForm):
    class Meta:
        model = models.Task
        fields = ['name', 'description', 'status', 'points', 'start_time', 'end_time']
        
    # 自定义验证方法
    def clean_start_time(self):
        start_time = self.cleaned_data.get('start_time')
        if start_time and start_time < datetime.now():  # 确保开始时间不早于当前时间
            raise forms.ValidationError("开始时间不能早于当前时间")
        return start_time
        
    def clean_end_time(self):
        end_time = self.cleaned_data.get('end_time')
        start_time = self.cleaned_data.get('start_time')
        if end_time and start_time and end_time <= start_time:  # 确保结束时间晚于开始时间
            raise forms.ValidationError("结束时间必须晚于开始时间")
        return end_time


# 创建任务
def create_task(request):
    """
    创建新任务API
    支持POST请求
    参数: name(任务名称), description(任务描述), status(任务状态), points(任务积分), start_time(开始时间), end_time(结束时间)
    返回: 创建成功的任务信息或错误信息
    """
    if request.method != 'POST':
        return response_dict(message="请使用POST请求", code=1)
    
    # 为任务生成唯一ID
    data = request.POST.dict()
    data['tid'] = str(uuid.uuid4())  # 生成UUID作为任务ID
    
    # 处理日期时间格式
    if 'start_time' in data and data['start_time']:
        try:
            data['start_time'] = datetime.strptime(data['start_time'], '%Y-%m-%d %H:%M:%S')
        except ValueError:
            return response_dict(message="开始时间格式错误，应为YYYY-MM-DD HH:MM:SS", code=1)
    else:
        data.pop('start_time', None)
        
    if 'end_time' in data and data['end_time']:
        try:
            data['end_time'] = datetime.strptime(data['end_time'], '%Y-%m-%d %H:%M:%S')
        except ValueError:
            return response_dict(message="结束时间格式错误，应为YYYY-MM-DD HH:MM:SS", code=1)
    else:
        data.pop('end_time', None)
    
    # 表单验证
    form = TaskForm(data)
    if not form.is_valid():
        return response_dict(data=get_first_error(form), code=1, message="参数错误")
    
    try:
        task = form.save(commit=False)  # 不立即保存
        task.user = request.user  # 设置用户关联
        task.save()  # 保存任务
        task_dict = task_utils.utils_model_to_dict(task)
        return response_dict(message="任务创建成功", code=0, data=task_dict)
    except Exception as e:
        return response_dict(message=f"创建失败: {str(e)}", code=1)


# 获取单个任务
def get_task(request):
    """
    获取单个任务详情API
    支持GET请求
    参数: tid(任务ID)
    返回: 任务详情或错误信息
    """
    if request.method != 'GET':
        return response_dict(message="请使用GET请求", code=1)

    # 验证任务是否属于该用户
    task_id = request.GET.get('tid')
    if not task_id:
        return response_dict(message="任务ID不能为空", code=1)
    
    try:
        task = models.Task.objects.get(tid=task_id, user=request.user)
        task_dict = task_utils.utils_model_to_dict(task)
        return response_dict(message="任务获取成功", code=0, data=task_dict)
    except models.Task.DoesNotExist:
        return response_dict(message="任务不存在", code=1)
    except Exception as e:
        return response_dict(message=f"获取失败: {str(e)}", code=1)


# 更新任务
def update_task(request):
    """
    更新任务信息API
    支持POST请求
    参数: tid(任务ID，必须), name(任务名称，可选), description(任务描述，可选), status(任务状态，可选), points(任务积分，可选), start_time(开始时间，可选), end_time(结束时间，可选)
    返回: 更新后的任务信息或错误信息
    功能: 仅更新请求中包含的字段，未包含的字段保持原有值不变
    特殊规则: 当任务状态为已完成或已取消时不允许更新，状态变为已完成时自动增加用户积分
    """
    if request.method != 'POST':
        return response_dict(message="请使用POST请求", code=1)
    
    task_id = request.POST.get('tid')
    if not task_id:
        return response_dict(message="任务ID不能为空", code=1)
    
    try:
        # 查找属于该用户的任务
        task = models.Task.objects.get(tid=task_id, user=request.user)
        
        # 检查任务是否已结束（当前时间大于结束时间）
        if task.end_time and datetime.now() > task.end_time:
            # 自动将任务状态设置为已取消（4）
            task.status = 4
            task.save()
            return response_dict(message="任务已结束，已自动设置为已取消状态，不允许更新", code=1)
        
        # 检查任务状态，如果已完成或已取消，则不允许更新
        if task.status in [3, 4]:
            status_text = "已完成" if task.status == 3 else "已取消"
            return response_dict(message=f"{status_text}的任务不允许再次更新", code=1)
        
        # 保存原始状态，用于后续判断是否从其他状态改为已完成
        original_status = task.status
        
        # 获取请求中所有字段
        post_data = request.POST.dict()
        
        # 需要排除的字段（任务ID不应该被更新）
        exclude_fields = ['tid']
        
        # 定义可更新的字段列表
        updatable_fields = ['name', 'description', 'status', 'points', 'start_time', 'end_time']
        
        # 验证结果存储
        validation_errors = {}
        
        # 处理日期时间字段和其他字段
        for field in updatable_fields:
            if field in post_data and field not in exclude_fields:
                value = post_data[field]
                
                # 根据字段类型进行处理
                if field == 'start_time':
                    if value:
                        try:
                            parsed_time = datetime.strptime(value, '%Y-%m-%d %H:%M:%S')
                            if parsed_time < datetime.now():
                                validation_errors[field] = "开始时间不能早于当前时间"
                            else:
                                setattr(task, field, parsed_time)
                        except ValueError:
                            validation_errors[field] = "开始时间格式错误，应为YYYY-MM-DD HH:MM:SS"
                    else:
                        setattr(task, field, None)
                elif field == 'end_time':
                    if value:
                        try:
                            parsed_time = datetime.strptime(value, '%Y-%m-%d %H:%M:%S')
                            # 检查结束时间是否晚于开始时间
                            if task.start_time and parsed_time <= task.start_time:
                                validation_errors[field] = "结束时间必须晚于开始时间"
                            else:
                                setattr(task, field, parsed_time)
                        except ValueError:
                            validation_errors[field] = "结束时间格式错误，应为YYYY-MM-DD HH:MM:SS"
                    else:
                        setattr(task, field, None)
                elif field == 'status':
                    if value:
                        try:
                            status_value = int(value)
                            # 检查状态值是否在允许的范围内
                            valid_statuses = [choice[0] for choice in models.Task._meta.get_field('status').choices]
                            if status_value not in valid_statuses:
                                validation_errors[field] = f"状态值必须是{valid_statuses}之一"
                            else:
                                setattr(task, field, status_value)
                        except ValueError:
                            validation_errors[field] = "状态值必须是整数"
                elif field == 'points':
                    if value:
                        try:
                            points_value = int(value)
                            if points_value < 0:
                                validation_errors[field] = "积分不能为负数"
                            else:
                                setattr(task, field, points_value)
                        except ValueError:
                            validation_errors[field] = "积分必须是整数"
                else:
                    # 其他字段直接设置
                    setattr(task, field, value)
        
        # 如果有验证错误，返回错误信息
        if validation_errors:
            # 获取第一个错误作为主要错误信息
            first_error_field = next(iter(validation_errors))
            first_error_message = validation_errors[first_error_field]
            return response_dict(data={first_error_field: first_error_message}, code=1, message="参数错误")
        
        # 保存更新后的任务
        task.save()
        
        # 检查是否是从其他状态改为已完成，如果是，则增加用户积分
        if original_status != 3 and task.status == 3:
            user = request.user
            user.points = (user.points or 0) + task.points
            user.save()
        
        # 返回更新后的任务信息
        task_dict = task_utils.utils_model_to_dict(task)
        return response_dict(message="任务更新成功", code=0, data=task_dict)
    except models.Task.DoesNotExist:
        return response_dict(message="任务不存在或不属于当前用户", code=1)
    except Exception as e:
        return response_dict(message=f"更新失败: {str(e)}", code=1)


# 删除任务
def delete_task(request):
    """
    删除任务API
    支持POST请求
    参数: tid(任务ID，必须)
    返回: 操作结果信息
    """
    if request.method != 'POST':
        return response_dict(message="请使用POST请求", code=1)
    
    task_id = request.POST.get('tid')
    if not task_id:
        return response_dict(message="任务ID不能为空", code=1)
    
    try:
        # 查找属于该用户的任务
        task = models.Task.objects.get(tid=task_id, user=request.user)
        task.delete()
        return response_dict(message="任务删除成功", code=0)
    except models.Task.DoesNotExist:
        return response_dict(message="任务不存在或不属于当前用户", code=1)
    except Exception as e:
        return response_dict(message=f"删除失败: {str(e)}", code=1)


# 获取全部任务列表
def get_task_list(request):
    """
    获取任务列表API
    支持GET请求
    参数: page_size(每页数量), page(页码), keyword(名称和描述的模糊查询关键字), status(任务状态筛选)
    返回: 分页任务列表或错误信息
    """
    if request.method != 'GET':
        return response_dict(message="请使用GET请求", code=1)
    
    # 获取查询参数
    page_size = request.GET.get('page_size')
    page = request.GET.get('page', 1)
    keyword = request.GET.get('keyword', '')
    status = request.GET.get('status', '')

    # 判断 page_size 是否存在
    if page_size is None:
        try:
            page_size = int(request.GET.get('limit', 10))
        except ValueError:
            return response_dict(message="limit参数必须是整数", code=1)
    
    # 构建查询条件
    query = Q(user=request.user)
    
    # 模糊查询
    if keyword:
        search_fields = Q(name__icontains=keyword) | Q(description__icontains=keyword)
        query &= search_fields
    
    # 状态筛选
    if status:
        query &= Q(status=int(status))
    
    # 分页处理
    page_data = get_page(models.Task.objects.filter(query).order_by('-create_time'), page_size, page) 
    
    # 转换为字典列表
    task_list = []
    for task in page_data['page']['object_list']:
        task_dict = task_utils.utils_model_to_dict(task)
        task_list.append(task_dict)
    
    del page_data['page']['object_list']
    
    # 构建返回数据
    result_data = {
        'list': task_list,
        "page": page_data['page']
    }
    
    return response_dict(message="任务列表获取成功", code=0, data=result_data)


# 任务统计API
def get_task_stats(request):
    """
    任务统计API
    支持GET请求
    返回: 用户任务状态统计信息及详细字段说明
    """
    if request.method != 'GET':
        return response_dict(message="请使用GET请求", code=1)
    
    try:
        # 统计各类状态的任务数量
        total_tasks = models.Task.objects.filter(user=request.user).count()
        not_started_tasks = models.Task.objects.filter(user=request.user, status=1).count()  # 1: 未开始
        in_progress_tasks = models.Task.objects.filter(user=request.user, status=2).count()  # 2: 进行中
        completed_tasks = models.Task.objects.filter(user=request.user, status=3).count()    # 3: 已完成
        canceled_tasks = models.Task.objects.filter(user=request.user, status=4).count()     # 4: 已取消
        
        # 构建统计结果
        stats_data = {
            "total_tasks": total_tasks,        # 总任务数量
            "not_started_tasks": not_started_tasks,  # 未开始任务数量
            "in_progress_tasks": in_progress_tasks,  # 进行中任务数量
            "completed_tasks": completed_tasks,      # 已完成任务数量
            "canceled_tasks": canceled_tasks,        # 已取消任务数量
        }
        
        return response_dict(message="任务统计信息获取成功", code=0, data=stats_data)
    except Exception as e:
        return response_dict(message=f"统计失败: {str(e)}", code=1)